package com.h3bpm.starcharge.support.utils;

import OThinker.H3.Entity.DataModel.BizObject;
import api.domain.template.create.LabelVO;
import com.h3bpm.starcharge.support.core.BasicContractsField;
import com.h3bpm.starcharge.support.core.H3FieldEntity;
import com.h3bpm.starcharge.support.core.annontation.ESealRequestParam;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * @ClassName ESealUtils
 * @Desciption 电子章工具类
 * @Author lvyz
 * @Date 2019/6/10 18:08
 **/
public class ESealUtils {

	private static final Logger log = LoggerFactory.getLogger(ESealUtils.class);

	/**
	 * BPM数据结构，转换为自定义数据结构（转换传递上上签数据结构之前调用）
	 *
	 * @param c
	 * @param valueTable
	 * @param <T>
	 * @return
	 */
	public static <T extends BasicContractsField> T toCustomEntity(Class<T> c, Map<String, Object> valueTable) throws Exception {

		T obj = c.newInstance();

		// 获取属性名称数组
		List<Field> fields = getAllField(c);

		// 便利数组
		for (Field field : fields) {

			// 获取转换属性自定义注解
			ESealRequestParam annotation = field.getAnnotation(ESealRequestParam.class);

			// 解析注解
			if (null == annotation) {
				continue;
			}

			// 设置属性忽略private修饰可以直接访问
			if (!Modifier.isPublic(field.getModifiers())
					|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
				field.setAccessible(true);
			}

			// 主属性
			if (!annotation.table()) {

				String key = annotation.bpmField();

				if (StringUtils.isBlank(key)) {
					continue;
				}

				// 设置实例的值
				field.set(obj, Objects.isNull(valueTable.get(key)) ? "" : valueTable.get(key).toString());

			}

			// 子表属性
			else {

				// 通过自定义注解中的子表名称，获取总数据中的子表数据
				BizObject[] tableDataList = (BizObject[]) valueTable.get(annotation.tableName());

				if(tableDataList != null){

					// 初始化存放子表单元格数据对象集合
					List<Map<String, String>> childList = new ArrayList<>();

					// 遍历子表数据
					for (BizObject tableData : tableDataList) {

						// 子表中一行数据
						Map<String, Object> rowMap = tableData.getValueTable();

						// 存放一行数据的集合 集合中的元素为 每一个单元格
						Map<String, String> _rowMap = new HashMap<>();

						// 通过自定义注解，获取bpm子表单元格名称集合
						String[] bpmChildFields = annotation.bpmColumnFields();

						// 遍历子表单元格名称集合，将子表数据和bpm字段名进行关联
						for (String bpmChildField : bpmChildFields) {

							String cellVal = Objects.isNull(rowMap.get(bpmChildField)) ? "" : String.valueOf(rowMap.get(bpmChildField));

							_rowMap.put(bpmChildField, cellVal);

						}

						childList.add(_rowMap);
					}

					field.set(obj, childList);
				}
			}
		}

		return obj;

	}

	/**
	 * 获取需要传递的参数
	 *
	 * @param entity
	 * @return
	 * @throws Exception
	 */
	public static List<LabelVO> getLabelList(BasicContractsField entity) throws Exception {

		if (null == entity) {
			throw new RuntimeException("entity can not be null");
		}

		List<LabelVO> labelList = new ArrayList<>();

		List<Field> fieldList = getAllField(entity.getClass());

		for (Field field : fieldList) {

			// 获取转换属性自定义注解
			ESealRequestParam annotation = field.getAnnotation(ESealRequestParam.class);

			// 解析注解
			if (null == annotation) {
				continue;
			}

			// 设置属性忽略private修饰可以直接访问
			if (!Modifier.isPublic(field.getModifiers())
					|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())) {
				field.setAccessible(true);
			}

			// 主数据
			if (!annotation.table()) {

				LabelVO label = new LabelVO();

				label.setName(annotation.eSealField());
				label.setValue(String.valueOf(field.get(entity)));

				labelList.add(label);

			}

			// 子表属性
			if (annotation.table()) {

				// 表数据
				List<Map<String, String>> tableData = (List<Map<String, String>>) field.get(entity);
				if(tableData != null) {
					for (int i = 0; i < tableData.size(); i++) {

						// 行数据
						Map<String, String> rowData = tableData.get(i);

						// 通过自定义注解，获取bpm子表单元格名称集合
						String[] eSealColumnFields = annotation.eSealColumnFields();
						String[] bpmColumnFields = annotation.bpmColumnFields();

						if (eSealColumnFields.length != bpmColumnFields.length) {
							throw new RuntimeException("Annotation ESealRequestParam eSealColumnFields length mast be equles bpmColumnFields length");
						}

						String index = "";
						if (i > 0) {
							index = String.valueOf(i);
						}

						for (int j = 0; j < bpmColumnFields.length; j++) {

							LabelVO label = new LabelVO();

							label.setName(eSealColumnFields[j] + index);
							label.setValue(rowData.get(bpmColumnFields[j]));

							labelList.add(label);

						}
					}
				}
			}
		}
		return labelList;
	}

	/**
	 * 取子表属性
	 *
	 * @param h3FieldEntities
	 * @param zbBizObjects
	 * @return
	 * @throws Exception
	 */
	private static List<LabelVO> getChild(List<H3FieldEntity> h3FieldEntities, BizObject[] zbBizObjects) throws Exception {

		List<LabelVO> labelList = new ArrayList<>();

		// 遍历值Map
		for (int i = 0; i < zbBizObjects.length; i++) {

			Map<String, Object> zbValueTable = zbBizObjects[i].getValueTable();

			String index = "";

			if (i > 0) {
				index = String.valueOf(i + 1);
			}

			// 遍历子表属性-设置子表属性值
			for (H3FieldEntity h3FieldEntity : h3FieldEntities) {

				LabelVO label = new LabelVO();
				label.setName(h3FieldEntity.getDisplayName() + index);
				label.setValue(String.valueOf(zbValueTable.get(h3FieldEntity.getName())));

				labelList.add(label);
			}
		}

		return labelList;
	}


	private void setField(Field field) {

	}


	/**
	 * 获取全部的属性包括父类
	 *
	 * @param clazz
	 * @return
	 */
	private static List<Field> getAllField(Class clazz) {

		List<Field> fieldList = new ArrayList<>();

		while (clazz != null) {
			fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
			clazz = clazz.getSuperclass();
		}

		Field[] fields = new Field[fieldList.size()];
		fieldList.toArray(fields);
		return fieldList;

	}

}
